#include "InSdkSignalFunc.h"
#include "InSdkAB6012BX.h"

#define DEF_TAG              "Signal"
#define DEF_BACKTRACE_SIZE   128

void InSdkSignal_Handler(int signal)
{
#if !CMAKE_INGENIC_T41N
    int j, nptrs;
    void *buffer[DEF_BACKTRACE_SIZE];
    char **strings;

    nptrs = backtrace(buffer, DEF_BACKTRACE_SIZE);
    PRT_WARN(DEF_TAG,"exit: backtrace() returned %d addresses, sig:%d\n", nptrs, signal);
#endif

    switch (signal)
    {
    case SIGINT: // 2:
        PRT_WARN(DEF_TAG,"The signal type: Interactive attention signal!\n");
        break;

    case SIGFPE: // 8:
        PRT_WARN(DEF_TAG,"The signal type: Floating point exception!\n");
        break;

    case SIGILL: // 4:
        PRT_WARN(DEF_TAG,"The signal type: Illegal instruction!\n");
        break;

    case SIGSEGV: // 11:
        PRT_WARN(DEF_TAG,"The signal type: Segmentation fault!\n");
        break;

    case SIGBUS: // 7:
        PRT_WARN(DEF_TAG,"The signal type: Bus error!\n");
        break;

    case SIGABRT: // 6:
        PRT_WARN(DEF_TAG,"The signal type: Aborted!\n");
        break;

    case SIGTRAP: // 5:
        PRT_WARN(DEF_TAG,"The signal type: Trace/breakpoint trap!\n");
        break;

    case SIGSYS: // 31:
        PRT_WARN(DEF_TAG,"The signal type: Bad system call!\n");
        break;

    case SIGTERM: // 15:
        PRT_WARN(DEF_TAG,"The signal type: Terminated!\n");
        break;

    case SIGQUIT: // 3:
        PRT_WARN(DEF_TAG,"The signal type: Quit!\n");
        break;

    case SIGKILL: // 9:
        PRT_WARN(DEF_TAG,"The signal type: Killed!\n");
        break;

    case SIGHUP: // 1:
        PRT_WARN(DEF_TAG,"The signal type: Hangup!\n");
        break;

    case SIGALRM: // 14:
        PRT_WARN(DEF_TAG,"The signal type: Alarm clock!\n");
        break;

    case SIGVTALRM: // 26:
        PRT_WARN(DEF_TAG,"The signal type: Virtual timer expired!\n");
        break;

    case SIGPROF: // 27:
        PRT_WARN(DEF_TAG,"The signal type: Profiling timer expired!\n");
        break;

    case SIGIO: // 29:
        PRT_WARN(DEF_TAG,"The signal type: I/O possible!\n");
        break;

    case SIGPIPE: // 13:
        PRT_WARN(DEF_TAG,"The signal type: Broken pipe!\n");
        break;

    case SIGXCPU: // 24:
        PRT_WARN(DEF_TAG,"The signal type: CPU time limit exceeded!\n");
        break;

    case SIGXFSZ: // 25:
        PRT_WARN(DEF_TAG,"The signal type: File size limit exceeded!\n");
        break;

    case SIGUSR1: // 10:
        PRT_WARN(DEF_TAG,"The signal type: User defined signal 1!\n");
        break;

    case SIGUSR2: // 12:
        PRT_WARN(DEF_TAG,"The signal type: User defined signal 2!\n");
        break;

    default:
        PRT_WARN(DEF_TAG,"The signal type: Unkown signal:%d!\n", signal);
        break;
    }

    /* The call backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO)
    would produce similar output to the following: */

#if !CMAKE_INGENIC_T41N
    strings = backtrace_symbols(buffer, nptrs);
    if (strings == NULL)
    {
        PRT_ERR(DEF_TAG,"backtrace_symbols");
        exit(EXIT_FAILURE);
    }

    for (j = 0; j < nptrs; j++)
    {
        PRT_ERR(DEF_TAG,"%s\n", strings[j]);
    }
    free(strings);
#endif

    if(signal != SIGPIPE)
    {
#if CMAKE_SUPPORT_AB6012BX
        JK_CloseBlue();
#endif
        PRT_DBG(DEF_TAG,"stop all thread now\n");
        g_ComThread_Running = DEF_COM_FALSE;
    }
}

void Ext_InSdkSignal_Init(void)
{
    signal(SIGINT, InSdkSignal_Handler);
    signal(SIGILL, InSdkSignal_Handler);
    signal(SIGBUS, InSdkSignal_Handler);
    signal(SIGFPE, InSdkSignal_Handler);
    signal(SIGABRT, InSdkSignal_Handler);
    signal(SIGTRAP, InSdkSignal_Handler);
    signal(SIGSYS, InSdkSignal_Handler);
    signal(SIGTERM, InSdkSignal_Handler);
    signal(SIGQUIT, InSdkSignal_Handler);
    signal(SIGKILL, InSdkSignal_Handler);
    signal(SIGHUP, InSdkSignal_Handler);
    signal(SIGALRM, SIG_IGN);
    signal(SIGVTALRM, InSdkSignal_Handler);
    signal(SIGPROF, InSdkSignal_Handler);
#if !CMAKE_SUPPORT_AB6012BX
    signal(SIGIO, InSdkSignal_Handler);
#endif
    signal(SIGPIPE, InSdkSignal_Handler);
    signal(SIGXCPU, InSdkSignal_Handler);
    signal(SIGXFSZ, InSdkSignal_Handler);
    signal(SIGUSR1, InSdkSignal_Handler);
    signal(SIGUSR2, InSdkSignal_Handler);
}
